Mapping underserved communities

The Tampa Bay Estuary Program (TBEP) is developing a methodology as part of its new Equity Strategy to identify historically underserved (i.e., disadvantaged) communities across the Tampa Bay watershed to support the goals of the White House’s Justice40 Initiative (EO 14008) and the Environmental Protection Agency’s Equity Action Plan (EO 13985). The purpose of this initiative is to ensure TBEP delivers equitable and fair access to the benefits from environmental programs for all communities.

Below, we have provided instructions for replicating our methodology for mapping underserved communities in Tampa Bay. To view instructions for downloading the necessary source data from EJScreen, see Getting EJScreen data.

While we encourage other National Estuary Programs to adopt our methodology in their own Equity Strategies, we recognize that different approaches may be necessary in different areas. Along with our descriptions of the methodology, we also briefly highlight the rationale behind our decisions, which may or may not be relevant or appropriate for other NEPs. If you have questions or other feedback regarding the methodology, contact Dr. Blake Simmons at bsimmons@tbep.org.

The method described below is presented in R coding language, but users who prefer working with GIS software (e.g., ArcGIS or QGIS) should also be able to reproduce the maps by following along in the descriptions of each step.

Load the required R packages (install first as needed).

library(sf)
library(mapview)
library(dplyr)
library(RColorBrewer)

Load and view the data.

load(file = 'data/dattb.RData')
mapview(dattb)

You can see that some census tracts are only representative of the bay. We can clean up this data by retaining only the tracts in which the total population recorded in the latest American Community Survey (“ACSTOTPOP”) was above zero. This will remove tracts in which no people reside (e.g., large waterbodies, parks, or other natural areas).

In line with EPA recommendations, we will use the following five demographic variables to identify underserved communities:

  • Percent classified as low income

  • Percent unemployed

  • Percent linguistically isolated (i.e., limited English speaking)

  • Percent with less than a high school education

  • Percent with low life expectancy

The EPA recommends flagging communities that fall within the 80th percentile (or higher) nationally as potentially disadvantaged. However, meeting this threshold in one variable alone is not necessarily an appropriate measure of disadvantage (e.g., a community of predominantly wealthy retirees would meet the unemployment threshold). For TBEP’s Equity Strategy, we define an underserved community as one that meets at least two of these thresholds, which we believe reduces the number of errors in identification while recognizing that a community does not need to meet the threshold of every indicator to face significant challenges.

Run the code below to (1) remove unpopulated census tracts, (2) count the number of demographic thresholds met in each tract, and (3) identify which tracts will be classified as “underserved” communities.

dattbindex <- dattb %>%
  filter(ACSTOTPOP > 0) %>%
  mutate(threshold_income = ifelse(P_LWINCPCT >= 80, 1, 0),
         threshold_unempl = ifelse(P_UNEMPPCT >= 80, 1, 0),
         threshold_lingui = ifelse(P_LNGISPCT >= 80, 1, 0),
         threshold_educat = ifelse(P_LESHSPCT >= 80, 1, 0),
         threshold_lifexp = ifelse(P_LIFEEXPCT >= 80, 1, 0)) %>%
  rowwise() %>%
  select(matches('^threshold|^ID')) %>% 
  mutate(threshold_N = sum(threshold_income,threshold_unempl,threshold_lingui,threshold_educat,threshold_lifexp, na.rm = TRUE)) %>%
  mutate(underserved = ifelse(threshold_N > 1, "Yes", "No"))

View the first five rows to see how the calculations have played out.

head(dattbindex)
Simple feature collection with 6 features and 8 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: -82.45127 ymin: 28.03256 xmax: -82.39752 ymax: 28.05464
Geodetic CRS:  WGS 84
# A tibble: 6 × 9
# Rowwise: 
  ID          thresh…¹ thres…² thres…³ thres…⁴ thres…⁵                     Shape
  <chr>          <dbl>   <dbl>   <dbl>   <dbl>   <dbl>             <POLYGON [°]>
1 12057000101        1       0       0       0      NA ((-82.42619 28.04506, -8…
2 12057000102        1       1       1       1       0 ((-82.42633 28.03258, -8…
3 12057000201        1       1       1       1       1 ((-82.4512 28.04362, -82…
4 12057000202        1       1       1       1      NA ((-82.44289 28.05294, -8…
5 12057000301        1       0       1       1       1 ((-82.45127 28.03364, -8…
6 12057000302        1       0       0       1       1 ((-82.43595 28.0391, -82…
# … with 2 more variables: threshold_N <dbl>, underserved <chr>, and
#   abbreviated variable names ¹​threshold_income, ²​threshold_unempl,
#   ³​threshold_lingui, ⁴​threshold_educat, ⁵​threshold_lifexp

View a map showing the number of thresholds met per census tract (you may adapt to a different color scale of your choice).

mapview(dattbindex, zcol = "threshold_N", col.regions = brewer.pal(6, "Reds"))

View the tracts that meet our definition of underserved communities. The areas in red are those that rank in the 80th percentile (or greater) nationally in 2 or more of the demographic screening variables. They will serve as priority areas for increasing the equitable distribution of benefits from TBEP’s environmental programs.

mapview(dattbindex, zcol = "underserved", col.regions = list("gray","red"))

You can save this final data as an RData object for future use.

# save the layer as an RData object
save(dattbindex, file = 'data/dattbindex.RData')